package com.example.demo.match;


import com.example.demo.RoomDeal.Room;
import com.example.demo.RoomDeal.RoomManager;
import com.example.demo.model.OnlineUserManager;
import com.example.demo.model.domian.User;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.LinkedList;
import java.util.Queue;

//匹配器,通过队列将不同分数的玩家放在不同的队列中
@Component
@Slf4j
public class Matcher {
    private Queue<User> nomalQueue=new LinkedList<>();
    private Queue<User> highQueue=new LinkedList<>();
    private Queue<User> veryHighQueue=new LinkedList<>();
    @Autowired
    private OnlineUserManager onlineUserManager;
    @Autowired
    private RoomManager roomManager;

    private ObjectMapper mapper=new ObjectMapper();

    //玩家点击开始匹配,根据天梯分进入不同的匹配队列中
    public void add(User user){

        if (user.getScore()<2000){
           synchronized (nomalQueue){
               nomalQueue.offer(user);
               nomalQueue.notify();
           }
            log.info("玩家 user {} 进入nomal匹配队列",user);
        }else if (user.getScore()>=2000&&user.getScore()<3000){
            log.info("玩家 user {} 进入highQueue匹配队列",user);
           synchronized (highQueue){
               highQueue.offer(user);
               highQueue.notify();
           }
        }else {
           synchronized (veryHighQueue){
               veryHighQueue.offer(user);
               veryHighQueue.notify();
           }
            log.info("玩家 user {} 进入veryHighQueue匹配队列",user);
        }
    }

    //玩家取消匹配
    public void remove(User user){
        if (user.getScore()<2000){
            log.info("玩家 user {} 从nomal匹配队列移除",user);
          synchronized (nomalQueue){
              nomalQueue.remove(user);
          }
        }else if (user.getScore()>=2000&&user.getScore()<3000){
          synchronized (highQueue){
              highQueue.remove(user);
          }
            log.info("玩家 user {} 从highQueue匹配队列移除",user);
        }else {
           synchronized (veryHighQueue){
               veryHighQueue.remove(user);
           }
            log.info("玩家 user {} 从veryHighQueue匹配队列移除",user);
        }
    }
    //用线程扫描,将玩家放入游戏房间
    public Matcher(){
       Thread t1=new Thread(){
           @Override
           public void run() {
               while (true){
                   handlerMatch(nomalQueue);
               }
           }
       };
       t1.start();
        Thread t2=new Thread(){
            @Override
            public void run() {
                while (true){

                    handlerMatch(highQueue);
                }
            }
        };
        t2.start();
        Thread t3=new Thread(){
            @Override
            public void run() {
                while (true){
                    handlerMatch(veryHighQueue);
                }
            }
        };
        t3.start();
    }

    private void handlerMatch(Queue<User> matchQueue) {
       synchronized (matchQueue){
           try {
               //看当前队列中是否已经有两个玩家
              while(matchQueue.size()<2){
                   matchQueue.wait();
               }
               //2.如果有两个玩家,就将队列中的元素取出
               User player1 = matchQueue.poll();
               User player2 = matchQueue.poll();
               log.info("当前队列玩家为player1 {},player2 {}",player1,player2);
               //通过session获取玩家信息,告知对方玩家你排到的人是谁
               WebSocketSession session1 = onlineUserManager.getFromGameHall(player1.getUserId());
               WebSocketSession session2 = onlineUserManager.getFromGameHall(player2.getUserId());


               //尽管我们在前面的逻辑中对多开以及下线都做了响应的处理,这里为了防止bug,进行二次校验
               if (session1==null){
                   matchQueue.offer(player2);
                   return;
               }
               if (session2==null){
                   matchQueue.offer(player1);
                   return;
               }
               if(session1==session2){
                   matchQueue.offer(player1);
                   return;
               }
               //4.把这两个玩家放到一个游戏房间中
               //这里room里面并没有用户信息,是因为避免出现问题玩家未进入房间
               Room room=new Room();
               roomManager.add(room, player1.getUserId(), player2.getUserId());

               //5.服务器告知匹配到对手了
               MatchResponse response1=new MatchResponse();
               response1.setOk(true);
               response1.setMessage("matchSuccess");
               session1.sendMessage(new TextMessage(mapper.writeValueAsString(response1)));


               MatchResponse response2=new MatchResponse();
               response2.setOk(true);
               response2.setMessage("matchSuccess");
               session2.sendMessage(new TextMessage(mapper.writeValueAsString(response2)));

           }catch (IOException e){
               e.printStackTrace();
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }
    }
}
